package nape.util;
#if flash9 import zpp_nape.Config;
import zpp_nape.Const;
import zpp_nape.util.Flags;
import DummyNapeMain;
import zpp_nape.util.Math;
import zpp_nape.util.Names;
import zpp_nape.util.Pool;
import zpp_nape.util.Lists;
import zpp_nape.shape.Circle;
import zpp_nape.shape.Edge;
import zpp_nape.space.Space;
import zpp_nape.shape.Polygon;
import zpp_nape.shape.Shape;
import zpp_nape.phys.FeatureMix;
import zpp_nape.phys.FluidProperties;
import zpp_nape.phys.Material;
import zpp_nape.phys.Body;
import zpp_nape.geom.AABB;
import zpp_nape.geom.Distance;
import zpp_nape.geom.Mat23;
import zpp_nape.geom.Vec2;
import zpp_nape.geom.VecMath;
import zpp_nape.geom.Collide;
import zpp_nape.dynamics.Arbiter;
import zpp_nape.dynamics.Contact;
import zpp_nape.dynamics.InteractionFilter;
import zpp_nape.constraint.Constraint;
import zpp_nape.dynamics.SpaceArbiterList;
import zpp_nape.constraint.Matrices;
import zpp_nape.constraint.PivotJoint;
import zpp_nape.constraint.WeldJoint;
import nape.util.Flags;
import nape.util.Lists;
import nape.space.Space;
import nape.shape.Circle;
import nape.shape.Polygon;
import nape.shape.Edge;
import nape.shape.Shape;
import nape.phys.FluidProperties;
import nape.phys.Material;
import nape.phys.Body;
import nape.geom.AABB;
import nape.geom.Geom;
import nape.geom.Mat23;
import nape.geom.Vec2;
import nape.dynamics.Contact;
import nape.dynamics.Arbiter;
import nape.dynamics.InteractionFilter;
import flash.display.Graphics;
#if swc@:keep#end class Debug{
    public var drawCollisionArbiters:Bool;
    public var drawFluidArbiters:Bool;
    public var drawSensorArbiters:Bool;
    public var drawBodyDetail:Bool;
    public var drawShapeDetail:Bool;
    public function new(){
        drawCollisionArbiters=false;
        drawFluidArbiters=false;
        drawSensorArbiters=false;
        drawBodyDetail=false;
        drawShapeDetail=false;
    }
    #if swc@:keep#end public function draw(graphics:Graphics,object:Dynamic){
        if(Std.is(object,Space)){
            var s:Space=object;
            for(o in s.bodies)draw(graphics,o);
            for(arb in s.arbiters)draw(graphics,arb);
        }
        else if(Std.is(object,Body)){
            var b:Body=object;
            for(s in b.shapes)draw(graphics,s);
            if(drawBodyDetail){
                var col={
                    var idc=Std.int(0xffffff*Math.exp(-b.id/1000));
                    var _r=(idc&0xff0000)>>>16;
                    var _g=(idc&0xff00)>>>8;
                    var _b=idc&0xff;
                    var sh=(b.space==null?false:b.isSleeping)?0.6:0.7;
                    (Std.int(_r*sh)<<16)|(Std.int(_g*sh)<<8)|Std.int(_b*sh);
                };
                graphics.lineStyle(0.1,0x800000|col,0.5);
                graphics.drawCircle(b.worldCOM.x,b.worldCOM.y,1);
                graphics.drawRect(b.bounds.x,b.bounds.y,b.bounds.width,b.bounds.height);
                graphics.lineStyle(0.1,0x400000|col,0.5);
                graphics.moveTo(b.position.x-0.747*2,b.position.y-0.747*2);
                graphics.lineTo(b.position.x+0.747*2,b.position.y+0.747*2);
                graphics.moveTo(b.position.x-0.747*2,b.position.y+0.747*2);
                graphics.lineTo(b.position.x+0.747*2,b.position.y-0.747*2);
                graphics.moveTo(b.position.x-1,b.position.y);
                graphics.lineTo(b.position.x+1,b.position.y);
                graphics.moveTo(b.position.x,b.position.y+1);
                graphics.lineTo(b.position.x,b.position.y-1);
            }
        }
        else if(Std.is(object,Shape)){
            var s:Shape=object;
            if(s.body!=null){
                var b=s.body;
                var col={
                    var idc=Std.int(0xffffff*Math.exp(-b.id/1000));
                    var _r=(idc&0xff0000)>>>16;
                    var _g=(idc&0xff00)>>>8;
                    var _b=idc&0xff;
                    var sh=(b.space==null?false:b.isSleeping)?0.6:0.7;
                    (Std.int(_r*sh)<<16)|(Std.int(_g*sh)<<8)|Std.int(_b*sh);
                };
                graphics.lineStyle(0.1,col,(b.space==null?false:b.isSleeping)?0.5:1);
                var alpha=if(b.isKinematic())0.333 else if(b.isStatic())0.666 else 0.0;
                if(b.space!=null&&b.isSleeping)alpha+=0.1;
                if(alpha!=0)graphics.beginFill(col,alpha);
                if(s.isCircle())graphics.drawCircle(s.circle.worldCOM.x,s.circle.worldCOM.y,s.circle.radius);
                else{
                    graphics.moveTo(s.worldCOM.x,s.worldCOM.y);
                    for(i in 0...s.polygon.worldVerts.length){
                        var p=s.polygon.worldVerts.at(i);
                        graphics.lineTo(p.x,p.y);
                    }
                    var p=s.polygon.worldVerts.at(0);
                    graphics.lineTo(p.x,p.y);
                }
                if(alpha!=0)graphics.endFill();
                if(s.isCircle()){
                    var c=s.circle;
                    var off=b.localToRelative(new Vec2(c.radius,0));
                    graphics.moveTo(c.worldCOM.x+off.x*0.333,c.worldCOM.y+off.y*0.333);
                    graphics.lineTo(c.worldCOM.x+off.x,c.worldCOM.y+off.y);
                }
                if(drawShapeDetail){
                    graphics.lineStyle(0.1,0x40|col,0.5);
                    graphics.drawCircle(s.worldCOM.x,s.worldCOM.y,1);
                    graphics.drawRect(s.bounds.x,s.bounds.y,s.bounds.width,s.bounds.height);
                }
            }
        }
        else if(Std.is(object,Arbiter)){
            var arb:Arbiter=object;
            if(arb.isSensorArbiter()){
                if(drawSensorArbiters){
                    var sarb=arb;
                    graphics.lineStyle(0.1,0xff00,1);
                    graphics.moveTo(sarb.shapeA.worldCOM.x,sarb.shapeA.worldCOM.y);
                    graphics.lineTo(sarb.shapeB.worldCOM.x,sarb.shapeB.worldCOM.y);
                }
            }
            else if(arb.isFluidArbiter()){
                if(drawFluidArbiters){
                    var farb=arb.fluidArbiter;
                    graphics.lineStyle(0.1,0xff,1);
                    graphics.drawCircle(farb.position.x,farb.position.y,0.75);
                }
            }
            else{
                if(drawCollisionArbiters){
                    var carb=arb.collisionArbiter;
                    for(c in carb.contacts)draw(graphics,c);
                }
            }
        }
        else if(Std.is(object,Contact)){
            var con:Contact=object;
            graphics.lineStyle(0.1,0xff0000,1);
            graphics.drawCircle(con.position.x,con.position.y,1.25);
        }
        else throw "Error: Cannot draw object : "+Std.string(object);
    }
}
#end